/*
 * @Date: 2025-01-18 16:45:14
 * @Author: LiSong
 * @LastEditors: LiSong
 * @LastEditTime: 2025-01-22 17:42:57
 * @Description: 收支预算数据计算工具类
 */

import { RKUtils, XEUtils } from '/@/utils';

/**
 * 处理数据小数点保留位数
 * 
 * @param value 数据
 * @param digits 保留小数点位数
 */
const formatValue = (value, digits = 2) => {
  value = value || 0
  return XEUtils.round(XEUtils.toNumber(value), digits)
}

/**
 * 解析打包计算公式数据
 * 
 * @param {Array} tableData 表格数据
 * @returns 
 */
export const packageFormulas = (tableData) => {
  // 计算格式提取 (string)key - (array)value
  let formulas = {};
  // 计算公式编码
  let formulaCode = {};
  // 计算公式别名
  let formulaAlias = {};
  // 计算公式需要操作的字段前缀
  let formulaFiled = {};

  for(let row of tableData) {
    const { BAL_FORMULA, IS_ZC_EDIT, IS_SR_EDIT } = row
    // 为空跳过
    if (!BAL_FORMULA) continue;
    let rowFormula = row.BAL_FORMULA.trim();
    if (IS_ZC_EDIT === 1) {
      formulaFiled[rowFormula] = 'ZCAMT_Y'
    }
    if (IS_SR_EDIT === 1) {
      formulaFiled[rowFormula] = 'SRAMT_Y'
    }
    // 设置公式对应的编码
    formulaCode[BAL_FORMULA] = row.BAL_TYPE_CODE
    if (BAL_FORMULA.includes('>=')) { // 是否包含大于符号
      parseFormula(rowFormula, '>=', formulas, row)
    }  else if (BAL_FORMULA.includes('<=')) { // 是否包含小于符号
      let rowFormulas = rowFormula.split('>=');
      formulaAlias[rowFormulas[0]] = {
        fls: rowFormula,
        name: row.BAL_TYPE_NAME.trim()
      }
    } else if (BAL_FORMULA.includes('=')) { // // 是否包含等号符号
      parseFormula(rowFormula, '=', formulas, row)
    } else {
      formulaAlias[rowFormula] = {
        fls: rowFormula,
        name: row.BAL_TYPE_NAME.trim()
      }
    }
  }
  /**
   * 设置公式数据
   * 
   * @param code 编码
   * @param formulas 公式对象
   * @param resFormulas 数据
   */
  function setFormulas (code, formulas, resFormulas) {
    if (formulas[code]) {
      formulas[code].push(resFormulas)
    } else {
      formulas[code] = [resFormulas]
    }
  }
  /**
   * 解析公式数据
   * 
   * @param rowFormula 行数据公式
   * @param splitCode 分隔符
   * @param formulas 公式数据集
   * @param row 行数据
   */
  function parseFormula (rowFormula, splitCode='=', formulas, row) {
    // 按=分割为数组
    let rowFormulas = rowFormula.split(splitCode);
    // 取出等号左边公式
    let fristLeftFl = rowFormulas[0];
    // 取出等号右边公式
    let lastRightFl = rowFormulas[1];
    // 判断特殊符号
    if (lastRightFl.includes('…')) {
      const rowCode = row.BAL_TYPE_CODE
      // 过滤该等式的其他变量
      const rowMark = tableData.filter(fRow => {
        return fRow.BAL_TYPE_CODE !== rowCode && fRow.BAL_TYPE_CODE.startsWith(rowCode)
      }).map(mRow => mRow.BAL_FORMULA)
      // 获取运算符号
      const operator = lastRightFl[lastRightFl.indexOf('…') - 1]
      lastRightFl = rowMark.join(operator)
    }
    // 公式结果集
    let resFormulas = [rowFormula, lastRightFl]
    // 拆分计算公式
    const calcFormulas = lastRightFl.replace(/(\(|\)|\-|\+|\*|\/)/g, ',').split(',').filter(f => f);
    resFormulas.push(...calcFormulas)
    // 设置别名
    formulaAlias[fristLeftFl] = {
      fls: rowFormula,
      name: row.BAL_TYPE_NAME.trim(),
      calcFormulas: resFormulas
    }
    const formulaCodes = lastRightFl.split(/[-+*/()]/);
    for(let code of formulaCodes) {
      if (!code) continue;
      setFormulas(code, formulas, resFormulas)
    }
  }

  return {
    formulas,
    formulaCode,
    formulaAlias,
    formulaFiled,
  }
}

/**
 * 工具公式计算数据
 * 
 * @param {String} gs 公式
 * @returns 
 */
const calculateFormulas = (gs) => {
	try {
		const func = new Function(`return ${gs}`)
    let result = func()
    result = isFinite(result) ? result : 0
		return result
	} catch (error) {
		console.error('计算公式出错', error)
		return 0
	}
}

/**
 * 计算表格数据
 * 
 * @param {Array} tableData 表格数据
 * @param {String} flsCode 当前行计算公式
 * @param {String} field 当前修改字段
 * @param {Object} tableStore 表格数据集
 * @returns 
 */
export const calculateRowByFormulas = (tableData, rowFls, field, tableStore) => {
  // 计算的总值
  let flsTotal = 0
  // 计算公式
  let rowFlsGs = rowFls[1]
  for (let i = 2; i < rowFls.length; i++) {
    let flCode = rowFls[i]
    const flRow = tableData.find(item => item.BAL_FORMULA === tableStore.formulaAlias[flCode].fls)
    const flField = field.replace(/\D+/g, tableStore.formulaFiled[flRow.BAL_FORMULA]);
    const flRowValue = formatValue(flRow[flField]) || 0
    rowFlsGs = rowFlsGs.replace(flCode, `(${flRowValue})`)
  }
  flsTotal = calculateFormulas(rowFlsGs)
  return flsTotal
}




const SzysUtils = {
  packageFormulas,
  calculateRowByFormulas,
}

export default SzysUtils
